<template>
  <div class="threejs-preview-container" ref="container">
    <div class="loading" v-if="loading">加载中...</div>
    <canvas ref="canvas"></canvas>

    <!-- 控制按钮 -->
    <div class="controls-panel">
      <button @click="resetView" title="重置视图">
        <i class="control-icon reset-icon">⟲</i>
      </button>
      <button @click="zoomIn" title="放大">
        <i class="control-icon">+</i>
      </button>
      <button @click="zoomOut" title="缩小">
        <i class="control-icon">-</i>
      </button>
      <button @click="toggleAutoRotate" :class="{ active: autoRotate }" title="自动旋转">
        <i class="control-icon rotate-icon">↻</i>
      </button>
      <button @click="takeScreenshot" title="截图">
        <i class="control-icon">📷</i>
      </button>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

export default {
  name: 'ThreejsPreview',
  props: {
    modelUrl: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      model: null,
      loading: true,
      autoRotate: false,
      initialCameraPosition: null,
      modelSize: 0
    };
  },
  mounted() {
    this.initThree();
    this.loadModel();
    window.addEventListener('resize', this.onWindowResize);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.onWindowResize);
    this.dispose();
  },
  methods: {
    initThree() {
      // 创建场景
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0xf0f0f0);

      // 创建相机
      const container = this.$refs.container;
      const aspect = container.clientWidth / container.clientHeight;
      this.camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
      this.camera.position.z = 5;

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({
        canvas: this.$refs.canvas,
        antialias: true
      });
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.outputEncoding = THREE.sRGBEncoding;

      // 添加光源
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
      this.scene.add(ambientLight);

      const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
      directionalLight.position.set(0, 1, 0);
      this.scene.add(directionalLight);

      // 添加控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;
      this.controls.autoRotate = this.autoRotate;
      this.controls.autoRotateSpeed = 3;

      // 开始动画循环
      this.animate();
    },
    loadModel() {
      const loader = new GLTFLoader();

      loader.load(
        this.modelUrl,
        (gltf) => {
          this.model = gltf.scene;

          // 计算模型的包围盒，用于自动调整相机位置
          const box = new THREE.Box3().setFromObject(this.model);
          const size = box.getSize(new THREE.Vector3()).length();
          const center = box.getCenter(new THREE.Vector3());

          // 保存模型大小，用于缩放操作
          this.modelSize = size;

          // 重置模型位置到场景中心
          this.model.position.x = -center.x;
          this.model.position.y = -center.y;
          this.model.position.z = -center.z;

          // 添加模型到场景
          this.scene.add(this.model);

          // 调整相机位置，确保模型完全可见
          this.camera.position.set(0, 0, size * 2);
          this.camera.lookAt(0, 0, 0);

          // 保存初始相机位置用于重置
          this.initialCameraPosition = this.camera.position.clone();

          // 调整控制器
          this.controls.target.set(0, 0, 0);
          this.controls.update();

          this.loading = false;
        },
        (progress) => {
          console.log('加载进度:', (progress.loaded / progress.total) * 100 + '%');
        },
        (error) => {
          console.error('加载模型出错:', error);
          this.loading = false;
        }
      );
    },
    animate() {
      requestAnimationFrame(this.animate);

      if (this.controls) {
        this.controls.update();
      }

      this.renderer.render(this.scene, this.camera);
    },
    onWindowResize() {
      const container = this.$refs.container;
      this.camera.aspect = container.clientWidth / container.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(container.clientWidth, container.clientHeight);
    },
    dispose() {
      // 清理Three.js资源
      if (this.model) {
        this.scene.remove(this.model);
        this.model.traverse((object) => {
          if (object.geometry) object.geometry.dispose();
          if (object.material) {
            if (Array.isArray(object.material)) {
              object.material.forEach(material => material.dispose());
            } else {
              object.material.dispose();
            }
          }
        });
      }

      if (this.controls) {
        this.controls.dispose();
      }

      this.renderer.dispose();
    },

    // 新增控制按钮方法
    resetView() {
      if (!this.initialCameraPosition) return;

      // 重置相机位置
      this.camera.position.copy(this.initialCameraPosition);
      this.camera.lookAt(0, 0, 0);

      // 重置控制器
      this.controls.target.set(0, 0, 0);
      this.controls.update();
    },

    zoomIn() {
      // 缩小相机距离，实现放大效果
      const zoomFactor = 0.8;
      this.camera.position.multiplyScalar(zoomFactor);
      this.controls.update();
    },

    zoomOut() {
      // 增加相机距离，实现缩小效果
      const zoomFactor = 1.25;
      this.camera.position.multiplyScalar(zoomFactor);
      this.controls.update();
    },

    toggleAutoRotate() {
      this.autoRotate = !this.autoRotate;
      this.controls.autoRotate = this.autoRotate;
    },

    takeScreenshot() {
      // 临时移除控制按钮，以便截图干净
      const controlsPanel = this.$el.querySelector('.controls-panel');
      const originalDisplay = controlsPanel.style.display;
      controlsPanel.style.display = 'none';

      // 重新渲染场景
      this.renderer.render(this.scene, this.camera);

      // 获取画布图像并下载
      this.renderer.domElement.toBlob((blob) => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = '3d-model-screenshot.png';
        a.click();

        // 释放URL资源
        setTimeout(() => URL.revokeObjectURL(url), 100);

        // 恢复控制按钮
        controlsPanel.style.display = originalDisplay;
      }, 'image/png');
    }
  }
};
</script>

<style scoped>
.threejs-preview-container {
  width: 100%;
  height: 400px;
  position: relative;
  overflow: hidden;
}

canvas {
  width: 100%;
  height: 100%;
  display: block;
}

.loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 18px;
  color: #666;
}

/* 控制按钮样式 */
.controls-panel {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
  background-color: rgba(255, 255, 255, 0.7);
  padding: 8px;
  border-radius: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.controls-panel button {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background-color: white;
  border: 1px solid #ddd;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
}

.controls-panel button:hover {
  background-color: #f0f0f0;
  transform: translateY(-2px);
}

.controls-panel button.active {
  background-color: #e6f7ff;
  border-color: #1890ff;
  color: #1890ff;
}

.control-icon {
  font-style: normal;
  font-size: 18px;
  line-height: 1;
}

.rotate-icon {
  font-size: 20px;
}

.reset-icon {
  font-size: 20px;
}
</style>
